home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / POV-Ray 3.0.2 / src / SOURCE / BBOX.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-06  |  36.3 KB  |  1,706 lines  |  [TEXT/CWIE]

  1. /*****************************************************************************
  2. *                bbox.c
  3. *
  4. *  This module implements the bounding box calculations.
  5. *  This file was written by Alexander Enzmann.    He wrote the code for
  6. *  POV-Ray's bounding boxes and generously provided us these enhancements.
  7. *  The box intersection code was further hacked by Eric Haines to speed it up.
  8. *
  9. *  Just so everyone knows where this came from, the code is VERY heavily
  10. *  based on the slab code from Mark VandeWettering's MTV raytracer.
  11. *  POV-Ray is just joining the crowd of admirers of Mark's contribution to
  12. *  the public domain. [ARE]
  13. *
  14. *  from Persistence of Vision(tm) Ray Tracer
  15. *  Copyright 1996 Persistence of Vision Team
  16. *---------------------------------------------------------------------------
  17. *  NOTICE: This source code file is provided so that users may experiment
  18. *  with enhancements to POV-Ray and to port the software to platforms other
  19. *  than those supported by the POV-Ray Team.  There are strict rules under
  20. *  which you are permitted to use this file.  The rules are in the file
  21. *  named POVLEGAL.DOC which should be distributed with this file. If
  22. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  23. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  24. *  Forum.  The latest version of POV-Ray may be found there as well.
  25. *
  26. * This program is based on the popular DKB raytracer version 2.12.
  27. * DKBTrace was originally written by David K. Buck.
  28. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  29. *
  30. *****************************************************************************/
  31.  
  32. #include "frame.h"
  33. #include "vector.h"
  34. #include "povproto.h"
  35. #include "bbox.h"
  36. #include "matrices.h"
  37. #include "objects.h"
  38. #include "povray.h"
  39. #include "render.h"
  40.  
  41.  
  42.  
  43. /*****************************************************************************
  44. * Local preprocessor defines
  45. ******************************************************************************/
  46.  
  47. #define BUNCHING_FACTOR 4
  48.  
  49. /* Initial number of entries in a priority queue. */
  50.  
  51. #define INITIAL_PRIORITY_QUEUE_SIZE 256
  52.  
  53.  
  54.  
  55. /*****************************************************************************
  56. * Local typedefs
  57. ******************************************************************************/
  58.  
  59.  
  60.  
  61. /*****************************************************************************
  62. * Static functions
  63. ******************************************************************************/
  64.  
  65. static BBOX_TREE *create_bbox_node PARAMS((int size));
  66.  
  67. static int find_axis PARAMS((BBOX_TREE **Finite, long first, long last));
  68. static void calc_bbox PARAMS((BBOX *BBox, BBOX_TREE **Finite, long first, long last));
  69. static void build_area_table PARAMS((BBOX_TREE **Finite, long a, long b, DBL *areas));
  70. static int sort_and_split PARAMS((BBOX_TREE **Root, BBOX_TREE **Finite, long *nFinite, long first, long last));
  71.  
  72. static void priority_queue_insert PARAMS((PRIORITY_QUEUE *Queue, DBL Depth, BBOX_TREE *Node));
  73.  
  74. static int CDECL compboxes PARAMS((CONST void *in_a, CONST void *in_b));
  75.  
  76.  
  77. /*****************************************************************************
  78. * Local variables
  79. ******************************************************************************/
  80.  
  81. /* Current axis to sort along. */
  82.  
  83. static int Axis = 0;
  84.  
  85. /* Number of finite elements. */
  86.  
  87. static long maxfinitecount = 0;
  88.  
  89. /* Priority queue used for frame level bouning box hierarchy. */
  90.  
  91. static PRIORITY_QUEUE *Frame_Queue;
  92.  
  93. /* Top node of bounding hierarchy. */
  94.  
  95. BBOX_TREE *Root_Object;
  96.  
  97.  
  98.  
  99. /*****************************************************************************
  100. *
  101. * FUNCTION
  102. *
  103. *   Initialize_BBox_Code
  104. *
  105. * INPUT
  106. *
  107. * OUTPUT
  108. *
  109. * RETURNS
  110. *
  111. * AUTHOR
  112. *
  113. *   Dieter Bayer
  114. *
  115. * DESCRIPTION
  116. *
  117. *   Initialize bbox specific variables.
  118. *
  119. * CHANGES
  120. *
  121. *   Jul 1995 : Creation.
  122. *
  123. ******************************************************************************/
  124.  
  125. void Initialize_BBox_Code()
  126. {
  127.   Frame_Queue = Create_Priority_Queue(INITIAL_PRIORITY_QUEUE_SIZE);
  128. }
  129.  
  130.  
  131.  
  132. /*****************************************************************************
  133. *
  134. * FUNCTION
  135. *
  136. *   Deinitialize_BBox_Code
  137. *
  138. * INPUT
  139. *
  140. * OUTPUT
  141. *
  142. * RETURNS
  143. *
  144. * AUTHOR
  145. *
  146. *   Dieter Bayer
  147. *
  148. * DESCRIPTION
  149. *
  150. *   Deinitialize bbox specific variables.
  151. *
  152. * CHANGES
  153. *
  154. *   Jul 1995 : Creation.
  155. *
  156. ******************************************************************************/
  157.  
  158. void Deinitialize_BBox_Code()
  159. {
  160.   if (Frame_Queue != NULL)
  161.   {
  162.     Destroy_Priority_Queue(Frame_Queue);
  163.   }
  164.  
  165.   Frame_Queue = NULL;
  166. }
  167.  
  168.  
  169.  
  170. /*****************************************************************************
  171. *
  172. * FUNCTION
  173. *
  174. *   Create_Priority_Queue
  175. *
  176. * INPUT
  177. *
  178. *   QSize - initial size of priority queue
  179. *
  180. * OUTPUT
  181. *
  182. * RETURNS
  183. *
  184. *   PRIORITY_QUEUE * - priority queue
  185. *
  186. * AUTHOR
  187. *
  188. *   Dieter Bayer
  189. *
  190. * DESCRIPTION
  191. *
  192. *   Create a priority queue.
  193. *
  194. * CHANGES
  195. *
  196. *   Feb 1995 : Creation.
  197. *
  198. ******************************************************************************/
  199.  
  200. PRIORITY_QUEUE *Create_Priority_Queue(QSize)
  201. unsigned QSize;
  202. {
  203.   PRIORITY_QUEUE *New;
  204.  
  205.   New = (PRIORITY_QUEUE *)POV_MALLOC(sizeof(PRIORITY_QUEUE), "priority queue");
  206.  
  207.   New->Queue = (QELEM *)POV_MALLOC(QSize*sizeof(QELEM), "priority queue");
  208.  
  209.   New->QSize = 0;
  210.  
  211.   New->Max_QSize = QSize;
  212.  
  213.   return (New);
  214. }
  215.  
  216.  
  217.  
  218. /*****************************************************************************
  219. *
  220. * FUNCTION
  221. *
  222. *   Destroy_Priority_Queue
  223. *
  224. * INPUT
  225. *
  226. *   Queue - Priority queue
  227. *
  228. * OUTPUT
  229. *
  230. * RETURNS
  231. *
  232. * AUTHOR
  233. *
  234. *   Dieter Bayer
  235. *
  236. * DESCRIPTION
  237. *
  238. *   Destroy a priority queue.
  239. *
  240. * CHANGES
  241. *
  242. *   Feb 1995 : Creation.
  243. *
  244. ******************************************************************************/
  245.  
  246. void Destroy_Priority_Queue(Queue)
  247. PRIORITY_QUEUE *Queue;
  248. {
  249.   if (Queue != NULL)
  250.   {
  251.     POV_FREE(Queue->Queue);
  252.  
  253.     POV_FREE(Queue);
  254.   }
  255. }
  256.  
  257.  
  258.  
  259. /*****************************************************************************
  260. *
  261. * FUNCTION
  262. *
  263. *   Destroy_BBox_Tree
  264. *
  265. * INPUT
  266. *
  267. *   Node - Node to destroy
  268. *
  269. * OUTPUT
  270. *
  271. * RETURNS
  272. *
  273. * AUTHOR
  274. *
  275. *   Dieter Bayer
  276. *
  277. * DESCRIPTION
  278. *
  279. *   Recursively destroy a bounding box tree.
  280. *
  281. * CHANGES
  282. *
  283. *   -
  284. *
  285. ******************************************************************************/
  286.  
  287. void Destroy_BBox_Tree(Node)
  288. BBOX_TREE *Node;
  289. {
  290.   short i;
  291.  
  292.   if (Node != NULL)
  293.   {
  294.     if (Node->Entries > 0)
  295.     {
  296.       for (i = 0; i < Node->Entries; i++)
  297.       {
  298.         Destroy_BBox_Tree(Node->Node[i]);
  299.       }
  300.  
  301.       POV_FREE(Node->Node);
  302.  
  303.       Node->Entries = 0;
  304.  
  305.       Node->Node = NULL;
  306.     }
  307.  
  308.     POV_FREE(Node);
  309.   }
  310. }
  311.  
  312.  
  313.  
  314. /*****************************************************************************
  315. *
  316. * FUNCTION
  317. *
  318. *   Recompute_BBox
  319. *
  320. * INPUT
  321. *
  322. *   trans - Transformation
  323. *
  324. * OUTPUT
  325. *
  326. *   bbox  - Bounding box
  327. *
  328. * RETURNS
  329. *
  330. * AUTHOR
  331. *
  332. *   Alexander Enzmann
  333. *
  334. * DESCRIPTION
  335. *
  336. *   Recalculate a bounding box after a transformation.
  337. *
  338. * CHANGES
  339. *
  340. *   -
  341. *
  342. ******************************************************************************/
  343.  
  344. void Recompute_BBox(bbox, trans)
  345. BBOX *bbox;
  346. TRANSFORM *trans;
  347. {
  348.   int i;
  349.   VECTOR lower_left, lengths, corner;
  350.   VECTOR mins, maxs;
  351.  
  352.   if (trans == NULL)
  353.   {
  354.     return;
  355.   }
  356.  
  357.   Assign_BBox_Vect(lower_left, bbox->Lower_Left);
  358.   Assign_BBox_Vect(lengths, bbox->Lengths);
  359.  
  360.   Make_Vector(mins, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
  361.   Make_Vector(maxs, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  362.  
  363.   for (i = 1; i <= 8; i++)
  364.   {
  365.     Assign_Vector(corner, lower_left);
  366.  
  367.     corner[X] += ((i & 1) ? lengths[X] : 0.0);
  368.     corner[Y] += ((i & 2) ? lengths[Y] : 0.0);
  369.     corner[Z] += ((i & 4) ? lengths[Z] : 0.0);
  370.  
  371.     MTransPoint(corner, corner, trans);
  372.  
  373.     if (corner[X] < mins[X]) { mins[X] = corner[X]; }
  374.     if (corner[X] > maxs[X]) { maxs[X] = corner[X]; }
  375.     if (corner[Y] < mins[Y]) { mins[Y] = corner[Y]; }
  376.     if (corner[Y] > maxs[Y]) { maxs[Y] = corner[Y]; }
  377.     if (corner[Z] < mins[Z]) { mins[Z] = corner[Z]; }
  378.     if (corner[Z] > maxs[Z]) { maxs[Z] = corner[Z]; }
  379.   }
  380.  
  381.   /* Clip bounding box at the largest allowed bounding box. */
  382.  
  383.   if (mins[X] < -BOUND_HUGE / 2) { mins[X] = -BOUND_HUGE / 2; }
  384.   if (mins[Y] < -BOUND_HUGE / 2) { mins[Y] = -BOUND_HUGE / 2; }
  385.   if (mins[Z] < -BOUND_HUGE / 2) { mins[Z] = -BOUND_HUGE / 2; }
  386.   if (maxs[X] >  BOUND_HUGE / 2) { maxs[X] =  BOUND_HUGE / 2; }
  387.   if (maxs[Y] >  BOUND_HUGE / 2) { maxs[Y] =  BOUND_HUGE / 2; }
  388.   if (maxs[Z] >  BOUND_HUGE / 2) { maxs[Z] =  BOUND_HUGE / 2; }
  389.  
  390.   Make_BBox_from_min_max(*bbox, mins, maxs);
  391. }
  392.  
  393.  
  394.  
  395. /*****************************************************************************
  396. *
  397. * FUNCTION
  398. *
  399. *   Recompute_Inverse_BBox
  400. *
  401. * INPUT
  402. *
  403. *   trans - Transformation
  404. *
  405. * OUTPUT
  406. *
  407. *   bbox  - Bounding box
  408. *
  409. * RETURNS
  410. *
  411. * AUTHOR
  412. *
  413. *   Alexander Enzmann
  414. *
  415. * DESCRIPTION
  416. *
  417. *   Recalculate a bounding box after a transformation.
  418. *
  419. * CHANGES
  420. *
  421. *   -
  422. *
  423. ******************************************************************************/
  424.  
  425. void Recompute_Inverse_BBox(bbox, trans)
  426. BBOX *bbox;
  427. TRANSFORM *trans;
  428. {
  429.   int i;
  430.   VECTOR lower_left, lengths, corner;
  431.   VECTOR mins, maxs;
  432.  
  433.   if (trans == NULL)
  434.   {
  435.     return;
  436.   }
  437.  
  438.   Assign_BBox_Vect(lower_left, bbox->Lower_Left);
  439.   Assign_BBox_Vect(lengths, bbox->Lengths);
  440.  
  441.   Make_Vector(mins, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
  442.   Make_Vector(maxs, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  443.  
  444.   for (i = 1; i <= 8; i++)
  445.   {
  446.     Assign_Vector(corner, lower_left);
  447.  
  448.     corner[X] += ((i & 1) ? lengths[X] : 0.0);
  449.     corner[Y] += ((i & 2) ? lengths[Y] : 0.0);
  450.     corner[Z] += ((i & 4) ? lengths[Z] : 0.0);
  451.  
  452.     MInvTransPoint(corner, corner, trans);
  453.  
  454.     if (corner[X] < mins[X]) { mins[X] = corner[X]; }
  455.     if (corner[X] > maxs[X]) { maxs[X] = corner[X]; }
  456.     if (corner[Y] < mins[Y]) { mins[Y] = corner[Y]; }
  457.     if (corner[Y] > maxs[Y]) { maxs[Y] = corner[Y]; }
  458.     if (corner[Z] < mins[Z]) { mins[Z] = corner[Z]; }
  459.     if (corner[Z] > maxs[Z]) { maxs[Z] = corner[Z]; }
  460.   }
  461.  
  462.   /* Clip bounding box at the largest allowed bounding box. */
  463.  
  464.   if (mins[X] < -BOUND_HUGE / 2) { mins[X] = -BOUND_HUGE / 2; }
  465.   if (mins[Y] < -BOUND_HUGE / 2) { mins[Y] = -BOUND_HUGE / 2; }
  466.   if (mins[Z] < -BOUND_HUGE / 2) { mins[Z] = -BOUND_HUGE / 2; }
  467.   if (maxs[X] >  BOUND_HUGE / 2) { maxs[X] =  BOUND_HUGE / 2; }
  468.   if (maxs[Y] >  BOUND_HUGE / 2) { maxs[Y] =  BOUND_HUGE / 2; }
  469.   if (maxs[Z] >  BOUND_HUGE / 2) { maxs[Z] =  BOUND_Hjects there are. */
  470.  
  471.   Render_Info("\nScene contains %ld frame level objects; %ld infinite.\n",
  472.       nFinite + nInfinite, nInfinite);
  473.  
  474.   /* If bounding boxes aren't used we can return. */
  475.  
  476.   if (!opts.Use_Slabs || !(nFinite + nInfinite >= opts.BBox_Threshold))
  477.   {
  478.     opts.Use_Slabs = FALSE; 
  479.  
  480.     return;
  481.   }
  482.  
  483.   opts.Use_Slabs = TRUE;
  484.  
  485.   /*
  486.    * This is a resonable guess at the number of finites needed.
  487.    * This array will be reallocated as needed if it isn't.
  488.    */
  489.  
  490.   maxfinitecount = 2 * nFinite;
  491.  
  492.   /*
  493.    * Now allocate an array to hold references to these finites and
  494.    * any new composite objects we may generate.
  495.    */
  496.  
  497.   Finite = Infinite = NULL;
  498.  
  499.   if (nFinite > 0)
  500.   {
  501.     Finite = (BBOX_TREE **)POV_MALLOC(maxfinitecount*sizeof(BBOX_TREE *), "bounding boxes");
  502.   }
  503.  
  504.   /* Create array to hold pointers to infinite objects. */
  505.  
  506.   if (nInfinite > 0)
  507.   {
  508.     Infinite = (BBOX_TREE **)POV_MALLOC(nInfinite*sizeof(BBOX_TREE *), "bounding boxes");
  509.   }
  510.  
  511.   /* Init lists. */
  512.  
  513.   for (i = 0; i < nFinite; i++)
  514.   {
  515.     Finite[i] = create_bbox_node(0);
  516.   }
  517.  
  518.   for (i = 0; i < nInfinite; i++)
  519.   {
  520.     Infinite[i] = create_bbox_node(0);
  521.   }
  522.  
  523.   /* Set up finite and infinite object lists. */
  524.  
  525.   iFinite = iInfinite = 0;
  526.  
  527.   for (Object = Frame.Objects; Object != NULL; Object = Object->Sibling)
  528.   {
  529.     if (Object->Type & LIGHT_SOURCE_OBJECT)
  530.     {
  531.       Temp = ((LIGHT_SOURCE *)Object)->Children;
  532.     }
  533.     else
  534.     {
  535.       Temp = Object;
  536.     }
  537.  
  538.     if (Temp != NULL)
  539.     {
  540.       /* Add object to the appropriate list. */
  541.  
  542.       if (Test_Flag(Temp, INFINITE_FLAG))
  543.       {
  544.         Infinite[iInfinite]->Infinite = TRUE;
  545.         Infinite[iInfinite]->BBox     = Temp->BBox;
  546.         Infinite[iInfinite]->Node     = (BBOX_TREE **)Temp;
  547.  
  548.         iInfinite++;
  549.       }
  550.       else
  551.       {
  552.         Finite[iFinite]->BBox = Temp->BBox;
  553.         Finite[iFinite]->Node = (BBOX_TREE **)Temp;
  554.  
  555.         iFinite++;
  556.       }
  557.     }
  558.   }
  559.  
  560.   /*
  561.    * Now build the bounding box tree.
  562.    */
  563.  
  564.   Build_BBox_Tree(Root, nFinite, Finite, nInfinite, Infinite);
  565.  
  566.   /* Get rid of the Finite and Infinite arrays and just use Root. */
  567.  
  568.   if (Finite != NULL)
  569.   {
  570.     POV_FREE(Finite);
  571.   }
  572.  
  573.   if (Infinite != NULL)
  574.   {
  575.     POV_FREE(Infinite);
  576.   }
  577. }
  578.  
  579.  
  580.  
  581. /*****************************************************************************
  582. *
  583. * FUNCTION
  584. *
  585. *   Destroy_Bounding_Slabs
  586. *
  587. * INPUT
  588. *
  589. * OUTPUT
  590. *
  591. * RETURNS
  592. *
  593. * AUTHOR
  594. *
  595. *   Alexander Enzmann
  596. *
  597. * DESCRIPTION
  598. *
  599. *   Destroy the bounding box hierarchy and the priority queue.
  600. *
  601. * CHANGES
  602. *
  603. *   Sep 1994 : Added freeing of priority queue. [DB]
  604. *
  605. ******************************************************************************/
  606.  
  607. void Destroy_Bounding_Slabs()
  608. {
  609.   if (Root_Object != NULL)
  610.   {
  611.     Destroy_BBox_Tree(Root_Object);
  612.  
  613.     Root_Object = NULL;
  614.   }
  615. }
  616.  
  617.  
  618.  
  619. /*****************************************************************************
  620. *
  621. * FUNCTION
  622. *
  623. *   Intersect_BBox_Tree
  624. *
  625. * INPUT
  626. *
  627. *   Root - Root node of the bbox tree
  628. *   Ray  - Current ray
  629. *
  630. * OUTPUT
  631. *
  632. *   Best_Intersection - Nearest intersection found
  633. *   Best_Object       - Nearest object found
  634. *
  635. * RETURNS
  636. *
  637. *   int - TRUE if an intersection was found
  638. *
  639. * AUTHOR
  640. *
  641. *   Alexander Enzmann
  642. *
  643. * DESCRIPTION
  644. *
  645. *   Intersect a ray with a bounding box tree.
  646. *
  647. * CHANGES
  648. *
  649. *   Sep 1994 : Moved priority queue allocation/freeing out of here. [DB]
  650. *
  651. ******************************************************************************/
  652.  
  653. int Intersect_BBox_Tree(Root, Ray, Best_Intersection, Best_Object)
  654. BBOX_TREE *Root;
  655. RAY *Ray;
  656. INTERSECTION *Best_Intersection;
  657. OBJECT **Best_Object;
  658. {
  659.   int i, found;
  660.   DBL Depth;
  661.   BBOX_TREE *Node;
  662.   RAYINFO rayinfo;
  663.   INTERSECTION New_Intersection;
  664.  
  665.   /* Create the direction vectors for this ray. */
  666.  
  667.   Create_Rayinfo(Ray, &rayinfo);
  668.  
  669.   /* Start with an empty priority queue. */
  670.  
  671.   found = FALSE;
  672.  
  673.   Frame_Queue->QSize = 0;
  674.  
  675. #ifdef BBOX_EXTRA_STATS
  676.   Increase_Counter(stats[totalQueueResets]);
  677. #endif
  678.  
  679.   /* Check top node. */
  680.  
  681.   Check_And_Enqueue(Frame_Queue, Root, &Root->BBox, &rayinfo);
  682.  
  683.   /* Check elements in the priority queue. */
  684.  
  685.   while (Frame_Queue->QSize)
  686.   {
  687.     Priority_Queue_Delete(Frame_Queue, &Depth, &Node);
  688.  
  689.     /*
  690.      * If current intersection is larger than the best intersection found
  691.      * so far our task is finished, because all other bounding boxes in
  692.      * the priority queue are further away.
  693.      */
  694.  
  695.     if (Depth > Best_Intersection->Depth)
  696.     {
  697.       break;
  698.     }
  699.  
  700.     /* Check current node. */
  701.  
  702.     if (Node->Entries)
  703.     {
  704.       /* This is a node containing leaves to be checked. */
  705.  
  706.       for (i = 0; i < Node->Entries; i++)
  707.       {
  708.         Check_And_Enqueue(Frame_Queue, Node->Node[i], &Node->Node[i]->BBox, &rayinfo);
  709.       }
  710.     }
  711.     else
  712.     {
  713.       /* This is a leaf so test contained object. */
  714.  
  715.       if (Intersection(&New_Intersection, (OBJECT *)Node->Node, Ray))
  716.       {
  717.         if (New_Intersection.Depth < Best_Intersection->Depth)
  718.         {
  719.           *Best_Intersection = New_Intersection;
  720.  
  721.           *Best_Object = (OBJECT *)Node->Node;
  722.  
  723.           found = TRUE;
  724.         }
  725.       }
  726.     }
  727.   }
  728.  
  729.   return (found);
  730. }
  731.  
  732.  
  733.  
  734. /*****************************************************************************
  735. *
  736. * FUNCTION
  737. *
  738. *   priority_queue_insert
  739. *
  740. * INPUT
  741. *   
  742. * OUTPUT
  743. *   
  744. * RETURNS
  745. *   
  746. * AUTHOR
  747. *
  748. *   Alexander Enzmann
  749. *   
  750. * DESCRIPTION
  751. *
  752. *   Insert an element in the priority queue.
  753. *
  754. * CHANGES
  755. *
  756. *   Sep 1994 : Added code for resizing the priority queue. [DB]
  757. *
  758. ******************************************************************************/
  759.  
  760. static void priority_queue_insert(Queue, Depth, Node)
  761. PRIORITY_QUEUE *Queue;
  762. DBL Depth;
  763. BBOX_TREE *Node;
  764. {
  765.   unsigned size;
  766.   int i;
  767.   QELEM tmp, *List;
  768.  
  769. #ifdef BBOX_EXTRA_STATS
  770.   Increase_Counter(stats[totalQueues]);
  771. #endif
  772.  
  773.   Queue->QSize++;
  774.  
  775.   size = Queue->QSize;
  776.  
  777.   /* Reallocate priority queue if it's too small. */
  778.  
  779.   if (size >= Queue->Max_QSize)
  780.   {
  781.     if (size >= INT_MAX/2)
  782.     {
  783.       Error("Priority queue overflow.\n");
  784.     }
  785.  
  786. #ifdef BBOX_EXTRA_STATS
  787.     Increase_Counter(stats[totalQueueResizes]);
  788. #endif
  789.  
  790.     Queue->Max_QSize *= 2;
  791.  
  792.     Queue->Queue = (QELEM *)POV_REALLOC(Queue->Queue, Queue->Max_QSize*sizeof(QELEM), "priority queue");
  793.   }
  794.  
  795.   List = Queue->Queue;
  796.   
  797.   List[size].Depth = Depth;
  798.   List[size].Node  = Node;
  799.   
  800.   i = size;
  801.   
  802.   while (i > 1 && List[i].Depth < List[i / 2].Depth)
  803.   {
  804.     tmp = List[i];
  805.  
  806.     List[i] = List[i / 2];
  807.  
  808.     List[i / 2] = tmp;
  809.  
  810.     i = i / 2;
  811.   }
  812. }
  813.  
  814.  
  815.  
  816. /*****************************************************************************
  817. *
  818. * FUNCTION
  819. *
  820. *   Priority_Queue_Delete
  821. *
  822. * INPUT
  823. *
  824. * OUTPUT
  825. *   
  826. * RETURNS
  827. *   
  828. * AUTHOR
  829. *
  830. *   Alexander Enzmann
  831. *   
  832. * DESCRIPTION
  833. *
  834. *   Get an element from the priority queue.
  835. *
  836. *   NOTE: This element will always be the one closest to the ray origin.
  837. *
  838. * CHANGES
  839. *
  840. *   -
  841. *
  842. ******************************************************************************/
  843.  
  844. void Priority_Queue_Delete(Queue, Depth, Node)
  845. PRIORITY_QUEUE *Queue;
  846. DBL *Depth;
  847. BBOX_TREE **Node;
  848. {
  849.   QELEM tmp, *List;
  850.   int i, j;
  851.   unsigned size;
  852.  
  853.   if (Queue->QSize == 0)
  854.   {
  855.     Error("priority queue is empty.\n");
  856.   }
  857.  
  858.   List = Queue->Queue;
  859.  
  860.   *Depth = List[1].Depth;
  861.   *Node  = List[1].Node;
  862.  
  863.   List[1] = List[Queue->QSize];
  864.  
  865.   Queue->QSize--;
  866.  
  867.   size = Queue->QSize;
  868.  
  869.   i = 1;
  870.  
  871.   while (2 * i <= (int)size)
  872.   {
  873.     if (2 * i == (int)size)
  874.     {
  875.       j = 2 * i;
  876.     }
  877.     else
  878.     {
  879.       if (List[2*i].Depth < List[2*i+1].Depth)
  880.       {
  881.         j = 2 * i;
  882.       }
  883.       else
  884.       {
  885.         j = 2 * i + 1;
  886.       }
  887.     }
  888.  
  889.     if (List[i].Depth > List[j].Depth)
  890.     {
  891.       tmp = List[i];
  892.  
  893.       List[i] = List[j];
  894.  
  895.       List[j] = tmp;
  896.  
  897.       i = j;
  898.     }
  899.     else
  900.     {
  901.       break;
  902.     }
  903.   }
  904. }
  905.  
  906.  
  907.  
  908. /*****************************************************************************
  909. *
  910. * FUNCTION
  911. *
  912. *   Check_And_Enqueue
  913. *
  914. * INPUT
  915. *
  916. * OUTPUT
  917. *
  918. * RETURNS
  919. *
  920. * AUTHOR
  921. *
  922. *   Alexander Enzmann
  923. *
  924. * DESCRIPTION
  925. *
  926. *   If a given ray intersect the object's bounding box then add it
  927. *   to the priority queue.
  928. *
  929. * CHANGES
  930. *
  931. *   Sep 1994 : Pass bounding box seperately.
  932. *              This is needed for the vista/light buffer. [DB]
  933. *
  934. *   Sep 1994 : Added code to insert infinte objects without testing. [DB]
  935. *
  936. ******************************************************************************/
  937.  
  938. void Check_And_Enqueue(Queue, Node, BBox, rayinfo)
  939. PRIORITY_QUEUE *Queue;
  940. BBOX_TREE *Node;
  941. BBOX *BBox;
  942. RAYINFO *rayinfo;
  943. {
  944.   DBL tmin, tmax;
  945.   DBL dmin, dmax;
  946.  
  947.   if (Node->Infinite)
  948.   {
  949.     /* Set intersection depth to -Max_Distance. */
  950.  
  951.     dmin = -Max_Distance;
  952.   }
  953.   else
  954.   {
  955.     Increase_Counter(stats[nChecked]);
  956.  
  957.     if (rayinfo->nonzero[X])
  958.     {
  959.       if (rayinfo->positive[X])
  960.       {
  961.         dmin = (BBox->Lower_Left[X] - rayinfo->slab_num[X]) *  rayinfo->slab_den[X];
  962.  
  963.         dmax = dmin + (BBox->Lengths[X]  * rayinfo->slab_den[X]);
  964.  
  965.         if (dmax < EPSILON) return;
  966.       }
  967.       else
  968.       {
  969.         dmax = (BBox->Lower_Left[X] - rayinfo->slab_num[X]) * rayinfo->slab_den[X];
  970.  
  971.         if (dmax < EPSILON) return;
  972.  
  973.         dmin = dmax + (BBox->Lengths[X]  * rayinfo->slab_den[X]);
  974.       }
  975.  
  976.       if (dmin > dmax) return;
  977.     }
  978.     else
  979.     {
  980.       if ((rayinfo->slab_num[X] < BBox->Lower_Left[X]) ||
  981.           (rayinfo->slab_num[X] > BBox->Lengths[X] + BBox->Lower_Left[X]))
  982.       {
  983.         return;
  984.       }
  985.  
  986.       dmin = -BOUND_HUGE;
  987.       dmax = BOUND_HUGE;
  988.     }
  989.  
  990.     if (rayinfo->nonzero[Y])
  991.     {
  992.       if (rayinfo->positive[Y])
  993.       {
  994.         tmin = (BBox->Lower_Left[Y] - rayinfo->slab_num[Y]) * rayinfo->slab_den[Y];
  995.  
  996.         tmax = tmin + (BBox->Lengths[Y]  * rayinfo->slab_den[Y]);
  997.       }
  998.       else
  999.       {
  1000.         tmax = (BBox->Lower_Left[Y] - rayinfo->slab_num[Y]) * rayinfo->slab_den[Y];
  1001.  
  1002.         tmin = tmax + (BBox->Lengths[Y]  * rayinfo->slab_den[Y]);
  1003.       }
  1004.  
  1005.       /*
  1006.        * Unwrap the logic - do the dmin and dmax checks only when tmin and
  1007.        * tmax actually affect anything, also try to escape ASAP. Better
  1008.        * yet, fold the logic below into the two branches above so as to
  1009.        *  compute only what is needed.
  1010.        */
  1011.  
  1012.       /*
  1013.        * You might even try tmax < EPSILON first (instead of second) for an
  1014.        * early quick out.
  1015.        */
  1016.  
  1017.       if (tmax < dmax)
  1018.       {
  1019.         if (tmax < EPSILON) return;
  1020.  
  1021.         /* check bbox only if tmax changes dmax */
  1022.  
  1023.         if (tmin > dmin)
  1024.         {
  1025.           if (tmin > tmax) return;
  1026.  
  1027.           /* do this last in case it's not needed! */
  1028.  
  1029.           dmin = tmin;
  1030.         }
  1031.         else
  1032.         {
  1033.           if (dmin > tmax) return;
  1034.         }
  1035.  
  1036.         /* do this last in case it's not needed! */
  1037.  
  1038.         dmax = tmax;
  1039.       }
  1040.       else
  1041.       {
  1042.         if (tmin > dmin)
  1043.         {
  1044.           if (tmin > dmax) return;
  1045.           
  1046.           /* do this last in case it's not needed! */
  1047.           
  1048.           dmin = tmin;
  1049.         }
  1050.  
  1051.         /* else nothing needs to happen, since dmin and dmax did not change! */
  1052.       }
  1053.     }
  1054.     else
  1055.     {
  1056.       if ((rayinfo->slab_num[Y] < BBox->Lower_Left[Y]) ||
  1057.           (rayinfo->slab_num[Y] > BBox->Lengths[Y] + BBox->Lower_Left[Y]))
  1058.       {
  1059.         return;
  1060.       }
  1061.     }
  1062.     
  1063.     if (rayinfo->nonzero[Z])
  1064.     {
  1065.       if (rayinfo->positive[Z])
  1066.       {
  1067.         tmin = (BBox->Lower_Left[Z] - rayinfo->slab_num[Z]) * rayinfo->slab_den[Z];
  1068.         
  1069.         tmax = tmin + (BBox->Lengths[Z]  * rayinfo->slab_den[Z]);
  1070.       }
  1071.       else
  1072.       {
  1073.         tmax = (BBox->Lower_Left[Z] - rayinfo->slab_num[Z]) * rayinfo->slab_den[Z];
  1074.  
  1075.         tmin = tmax + (BBox->Lengths[Z]  * rayinfo->slab_den[Z]);
  1076.       }
  1077.  
  1078.       if (tmax < dmax)
  1079.       {
  1080.         if (tmax < EPSILON) return;
  1081.  
  1082.         /* check bbox only if tmax changes dmax */
  1083.  
  1084.         if (tmin > dmin)
  1085.         {
  1086.           if (tmin > tmax) return;
  1087.  
  1088.           /* do this last in case it's not needed! */
  1089.  
  1090.           dmin = tmin;
  1091.         }
  1092.         else
  1093.         {
  1094.           if (dmin > tmax) return;
  1095.         }
  1096.       }
  1097.       else
  1098.       {
  1099.         if (tmin > dmin)
  1100.         {
  1101.           if (tmin > dmax) return;
  1102.  
  1103.           /* do this last in case it's not needed! */
  1104.  
  1105.           dmin = tmin;
  1106.         }
  1107.  
  1108.         /* else nothing needs to happen, since dmin and dmax did not change! */
  1109.       }
  1110.     }
  1111.     else
  1112.     {
  1113.       if ((rayinfo->slab_num[Z] < BBox->Lower_Left[Z]) ||
  1114.           (rayinfo->slab_num[Z] > BBox->Lengths[Z] + BBox->Lower_Left[Z]))
  1115.       {
  1116.         return;
  1117.       }
  1118.     }
  1119.  
  1120.     Increase_Counter(stats[nEnqueued]);
  1121.   }
  1122.  
  1123.   priority_queue_insert(Queue, dmin, Node);
  1124. }
  1125.  
  1126.  
  1127.  
  1128. /*****************************************************************************
  1129. *
  1130. * FUNCTION
  1131. *
  1132. *   Create_Rayinfo
  1133. *
  1134. * INPUT
  1135. *
  1136. *   Ray     - Current ray
  1137. *   rayinfo - Rayinfo structure
  1138. *   
  1139. * OUTPUT
  1140. *
  1141. *   rayinfo
  1142. *   
  1143. * RETURNS
  1144. *   
  1145. * AUTHOR
  1146. *
  1147. *   Dieter Bayer
  1148. *   
  1149. * DESCRIPTION
  1150. *
  1151. *   Calculate the rayinfo structure for a given ray. It's need for
  1152. *   intersection the ray with bounding boxes.
  1153. *
  1154. * CHANGES
  1155. *
  1156. *   May 1994 : Creation. (Extracted from Intersect_BBox_Tree)
  1157. *
  1158. ******************************************************************************/
  1159.  
  1160. void Create_Rayinfo(Ray, rayinfo)
  1161. RAY *Ray;
  1162. RAYINFO *rayinfo;
  1163. {
  1164.   DBL t;
  1165.  
  1166.   /* Create the direction vectors for this ray */
  1167.  
  1168.   Assign_Vector(rayinfo->slab_num, Ray->Initial);
  1169.  
  1170.   if ((rayinfo->nonzero[X] = ((t = Ray->Direction[X]) != 0.0)) != 0)
  1171.   {
  1172.     rayinfo->slab_den[X] = 1.0 / t;
  1173.  
  1174.     rayinfo->positive[X] = (Ray->Direction[X] > 0.0);
  1175.   }
  1176.  
  1177.   if ((rayinfo->nonzero[Y] = ((t = Ray->Direction[Y]) != 0.0)) != 0)
  1178.   {
  1179.     rayinfo->slab_den[Y] = 1.0 / t;
  1180.  
  1181.     rayinfo->positive[Y] = (Ray->Direction[Y] > 0.0);
  1182.   }
  1183.  
  1184.   if ((rayinfo->nonzero[Z] = ((t = Ray->Direction[Z]) != 0.0)) != 0)
  1185.   {
  1186.     rayinfo->slab_den[Z] = 1.0 / t;
  1187.  
  1188.     rayinfo->positive[Z] = (Ray->Direction[Z] > 0.0);
  1189.   }
  1190. }
  1191.  
  1192.  
  1193.  
  1194. /*****************************************************************************
  1195. *
  1196. * FUNCTION
  1197. *
  1198. *   create_bbox_node
  1199. *
  1200. * INPUT
  1201. *
  1202. *   size - Number of subnodes
  1203. *
  1204. * OUTPUT
  1205. *
  1206. * RETURNS
  1207. *
  1208. *   BBOX_TREE * - New node
  1209. *
  1210. * AUTHOR
  1211. *
  1212. *   Alexander Enzmann
  1213. *   
  1214. * DESCRIPTION
  1215. *
  1216. *   -
  1217. *
  1218. * CHANGES
  1219. *
  1220. *   -
  1221. *
  1222. ******************************************************************************/
  1223.  
  1224. static BBOX_TREE *create_bbox_node(size)
  1225. int size;
  1226. {
  1227.   BBOX_TREE *New;
  1228.  
  1229.   New = (BBOX_TREE *)POV_MALLOC(sizeof(BBOX_TREE), "bounding box node");
  1230.  
  1231.   New->Infinite = FALSE;
  1232.  
  1233.   New->Entries = size;
  1234.  
  1235.   Make_BBox(New->BBox, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
  1236.  
  1237.   if (size)
  1238.   {
  1239.     New->Node = (BBOX_TREE **)POV_MALLOC(size*sizeof(BBOX_TREE *), "bounding box node");
  1240.   }
  1241.   else
  1242.   {
  1243.     New->Node = NULL;
  1244.   }
  1245.  
  1246.   return (New);
  1247. }
  1248.  
  1249.  
  1250.  
  1251. /*****************************************************************************
  1252. *
  1253. * FUNCTION
  1254. *
  1255. *   compboxes
  1256. *
  1257. * INPUT
  1258. *
  1259. *   in_a, in_b - Elements to compare
  1260. *
  1261. * OUTPUT
  1262. *
  1263. * RETURNS
  1264. *
  1265. *   int - result of comparison
  1266. *
  1267. * AUTHOR
  1268. *
  1269. *   Alexander Enzmann
  1270. *
  1271. * DESCRIPTION
  1272. *
  1273. *   -
  1274. *
  1275. * CHANGES
  1276. *
  1277. *   Sep 1994 : Removed test for infinite objects because it's obsolete. [DB]
  1278. *
  1279. ******************************************************************************/
  1280.  
  1281. static int CDECL compboxes(in_a, in_b)
  1282. CONST void *in_a;
  1283. CONST void *in_b;
  1284. {
  1285.   BBOX *a, *b;
  1286.   BBOX_VAL am, bm;
  1287.  
  1288.   a = &((*(BBOX_TREE **)in_a)->BBox);
  1289.   b = &((*(BBOX_TREE **)in_b)->BBox);
  1290.  
  1291.   am = 2.0 * a->Lower_Left[Axis] + a->Lengths[Axis];
  1292.   bm = 2.0 * b->Lower_Left[Axis] + b->Lengths[Axis];
  1293.  
  1294.   if (am < bm)
  1295.   {
  1296.     return (-1);
  1297.   }
  1298.   else
  1299.   {
  1300.     if (am == bm)
  1301.     {
  1302.       return (0);
  1303.     }
  1304.     else
  1305.     {
  1306.       return (1);
  1307.     }
  1308.   }
  1309. }
  1310.  
  1311.  
  1312.  
  1313. /*****************************************************************************
  1314. *
  1315. * FUNCTION
  1316. *
  1317. *   find_axis
  1318. *
  1319. * INPUT
  1320. *
  1321. *   Finite      - Array of finite elements
  1322. *   first, last - Position of elements
  1323. *
  1324. * OUTPUT
  1325. *   
  1326. * RETURNS
  1327. *
  1328. *   int - Axis to sort along
  1329. *   
  1330. * AUTHOR
  1331. *
  1332. *   Alexander Enzmann
  1333. *   
  1334. * DESCRIPTION
  1335. *
  1336. *   Find the axis along which the elements will be sorted.
  1337. *
  1338. * CHANGES
  1339. *
  1340. *   Sep 1994 : Initialize local variable which. [DB]
  1341. *
  1342. ******************************************************************************/
  1343.  
  1344. static int find_axis(Finite, first, last)
  1345. BBOX_TREE **Finite;
  1346. long first, last;
  1347. {
  1348.   int which = X;
  1349.   long i;
  1350.   DBL e, d = -BOUND_HUGE;
  1351.   VECTOR mins, maxs;
  1352.   BBOX *bbox;
  1353.  
  1354.   Make_Vector(mins, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
  1355.   Make_Vector(maxs, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  1356.  
  1357.   for (i = first; i < last; i++)
  1358.   {
  1359.     bbox = &(Finite[i]->BBox);
  1360.  
  1361.     if (bbox->Lower_Left[X] < mins[X])
  1362.     {
  1363.       mins[X] = bbox->Lower_Left[X];
  1364.     }
  1365.  
  1366.     if (bbox->Lower_Left[X] + bbox->Lengths[X] > maxs[X])
  1367.     {
  1368.       maxs[X] = bbox->Lower_Left[X];
  1369.     }
  1370.  
  1371.     if (bbox->Lower_Left[Y] < mins[Y])
  1372.     {
  1373.       mins[Y] = bbox->Lower_Left[Y];
  1374.     }
  1375.  
  1376.     if (bbox->Lower_Left[Y] + bbox->Lengths[Y] > maxs[Y])
  1377.     {
  1378.       maxs[Y] = bbox->Lower_Left[Y];
  1379.     }
  1380.  
  1381.     if (bbox->Lower_Left[Z] < mins[Z])
  1382.     {
  1383.       mins[Z] = bbox->Lower_Left[Z];
  1384.     }
  1385.  
  1386.     if (bbox->Lower_Left[Z] + bbox->Lengths[Z] > maxs[Z])
  1387.     {
  1388.       maxs[Z] = bbox->Lower_Left[Z];
  1389.     }
  1390.   }
  1391.  
  1392.   e = maxs[X] - mins[X];
  1393.  
  1394.   if (e > d)
  1395.   {
  1396.     d = e;  which = X;
  1397.   }
  1398.  
  1399.   e = maxs[Y] - mins[Y];
  1400.  
  1401.   if (e > d)
  1402.   {
  1403.     d = e;  which = Y;
  1404.   }
  1405.  
  1406.   e = maxs[Z] - mins[Z];
  1407.  
  1408.   if (e > d)
  1409.   {
  1410.     which = Z;
  1411.   }
  1412.  
  1413.   return (which);
  1414. }
  1415.  
  1416.  
  1417.  
  1418. /*****************************************************************************
  1419. *
  1420. * FUNCTION
  1421. *
  1422. *   calc_bbox
  1423. *
  1424. * INPUT
  1425. *   
  1426. * OUTPUT
  1427. *   
  1428. * RETURNS
  1429. *   
  1430. * AUTHOR
  1431. *
  1432. *   Alexander Enzmann
  1433. *   
  1434. * DESCRIPTION
  1435. *
  1436. *   Calculate the bounding box containing Finite[first] through Finite[last-1].
  1437. *
  1438. * CHANGES
  1439. *
  1440. *   -
  1441. *
  1442. ******************************************************************************/
  1443.  
  1444. static void calc_bbox(BBox, Finite, first, last)
  1445. BBOX *BBox;
  1446. BBOX_TREE **Finite;
  1447. long first, last;
  1448. {
  1449.   long i;
  1450.   DBL tmin, tmax;
  1451.   VECTOR bmin, bmax;
  1452.   BBOX *bbox;
  1453.  
  1454.   COOPERATE_1
  1455.  
  1456.   Make_Vector(bmin, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
  1457.   Make_Vector(bmax, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  1458.  
  1459.   for (i = first; i < last; i++)
  1460.   {
  1461.     bbox = &(Finite[i]->BBox);
  1462.  
  1463.     tmin = bbox->Lower_Left[X];
  1464.     tmax = tmin + bbox->Lengths[X];
  1465.  
  1466.     if (tmin < bmin[X]) { bmin[X] = tmin; }
  1467.     if (tmax > bmax[X]) { bmax[X] = tmax; }
  1468.  
  1469.     tmin = bbox->Lower_Left[Y];
  1470.     tmax = tmin + bbox->Lengths[Y];
  1471.  
  1472.     if (tmin < bmin[Y]) { bmin[Y] = tmin; }
  1473.     if (tmax > bmax[Y]) { bmax[Y] = tmax; }
  1474.  
  1475.     tmin = bbox->Lower_Left[Z];
  1476.     tmax = tmin + bbox->Lengths[Z];
  1477.  
  1478.     if (tmin < bmin[Z]) { bmin[Z] = tmin; }
  1479.     if (tmax > bmax[Z]) { bmax[Z] = tmax; }
  1480.   }
  1481.  
  1482.   Make_BBox_from_min_max(*BBox, bmin, bmax);
  1483. }
  1484.  
  1485.  
  1486.  
  1487. /*****************************************************************************
  1488. *
  1489. * FUNCTION
  1490. *
  1491. *   build_area_table
  1492. *
  1493. * INPUT
  1494. *   
  1495. * OUTPUT
  1496. *   
  1497. * RETURNS
  1498. *   
  1499. * AUTHOR
  1500. *
  1501. *   Alexander Enzmann
  1502. *   
  1503. * DESCRIPTION
  1504. *
  1505. *   Generates a table of bound box surface areas.
  1506. *
  1507. * CHANGES
  1508. *
  1509. *   -
  1510. *
  1511. ******************************************************************************/
  1512.  
  1513. static void build_area_table(Finite, a, b, areas)
  1514. BBOX_TREE **Finite;
  1515. long a, b;
  1516. DBL *areas;
  1517. {
  1518.   long i, imin, dir;
  1519.   DBL tmin, tmax;
  1520.   VECTOR bmin, bmax, len;
  1521.   BBOX *bbox;
  1522.  
  1523.   if (a < b)
  1524.   {
  1525.     imin = a;  dir =  1;
  1526.   }
  1527.   else
  1528.   {
  1529.     imin = b;  dir = -1;
  1530.   }
  1531.  
  1532.   Make_Vector(bmin, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
  1533.   Make_Vector(bmax, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  1534.  
  1535.   for (i = a; i != (b + dir); i += dir)
  1536.   {
  1537.     bbox = &(Finite[i]->BBox);
  1538.  
  1539.     tmin = bbox->Lower_Left[X];
  1540.     tmax = tmin + bbox->Lengths[X];
  1541.  
  1542.     if (tmin < bmin[X]) { bmin[X] = tmin; }
  1543.     if (tmax > bmax[X]) { bmax[X] = tmax; }
  1544.  
  1545.     tmin = bbox->Lower_Left[Y];
  1546.     tmax = tmin + bbox->Lengths[Y];
  1547.  
  1548.     if (tmin < bmin[Y]) { bmin[Y] = tmin; }
  1549.     if (tmax > bmax[Y]) { bmax[Y] = tmax; }
  1550.  
  1551.     tmin = bbox->Lower_Left[Z];
  1552.     tmax = tmin + bbox->Lengths[Z];
  1553.  
  1554.     if (tmin < bmin[Z]) { bmin[Z] = tmin; }
  1555.     if (tmax > bmax[Z]) { bmax[Z] = tmax; }
  1556.  
  1557.     VSub(len, bmax, bmin);
  1558.  
  1559.     areas[i - imin] = len[X] * (len[Y] + len[Z]) + len[Y] * len[Z];
  1560.   }
  1561. }
  1562.  
  1563.  
  1564.  
  1565. /*****************************************************************************
  1566. *
  1567. * FUNCTION
  1568. *
  1569. *   sort_and_split
  1570. *
  1571. * INPUT
  1572. *
  1573. * OUTPUT
  1574. *
  1575. * RETURNS
  1576. *
  1577. * AUTHOR
  1578. *
  1579. *   Alexander Enzmann
  1580. *
  1581. * DESCRIPTION
  1582. *
  1583. *   -
  1584. *
  1585. * CHANGES
  1586. *
  1587. *   -
  1588. *
  1589. ******************************************************************************/
  1590.  
  1591. static int sort_and_split(Root, Finite, nFinite, first, last)
  1592. BBOX_TREE **Root;
  1593. BBOX_TREE **Finite;
  1594. long *nFinite, first, last;
  1595. {
  1596.   BBOX_TREE *cd;
  1597.   long size, i, best_loc;
  1598.   DBL *area_left, *area_right;
  1599.   DBL best_index, new_index;
  1600.  
  1601.   Axis = find_axis(Finite, first, last);
  1602.  
  1603.   size = last - first;
  1604.  
  1605.   if (size <= 0)
  1606.   {
  1607.     return (1);
  1608.   }
  1609.  
  1610.   /*
  1611.    * Actually, we could do this faster in several ways. We could use a
  1612.    * logn algorithm to find the median along the given axis, and then a
  1613.    * linear algorithm to partition along the axis. Oh well.
  1614.    */
  1615.  
  1616.   QSORT((void *)(&Finite[first]), (unsigned long)size, sizeof(BBOX_TREE *), compboxes);
  1617.  
  1618.   /*
  1619.    * area_left[] and area_right[] hold the surface areas of the bounding
  1620.    * boxes to the left and right of any given point. E.g. area_left[i] holds
  1621.    * the surface area of the bounding box containing Finite 0 through i and
  1622.    * area_right[i] holds the surface area of the box containing Finite
  1623.    * i through size-1.
  1624.    */
  1625.  
  1626.   area_left = (DBL *)POV_MALLOC(size * sizeof(DBL), "bounding boxes");
  1627.   area_right = (DBL *)POV_MALLOC(size * sizeof(DBL), "bounding boxes");
  1628.  
  1629.   /* Precalculate the areas for speed. */
  1630.  
  1631.   build_area_table(Finite, first, last - 1, area_left);
  1632.   build_area_table(Finite, last - 1, first, area_right);
  1633.  
  1634.   best_index = area_right[0] * (size - 3.0);
  1635.  
  1636.   best_loc = -1;
  1637.  
  1638.   /*
  1639.    * Find the most effective point to split. The best location will be
  1640.    * the one that minimizes the function N1*A1 + N2*A2 where N1 and N2
  1641.    * are the number of objects in the two groups and A1 and A2 are the
  1642.    * surface areas of the bounding boxes of the two groups.
  1643.    */
  1644.  
  1645.   for (i = 0; i < size - 1; i++)
  1646.   {
  1647.     new_index = (i + 1) * area_left[i] + (size - 1 - i) * area_right[i + 1];
  1648.  
  1649.     if (new_index < best_index)
  1650.     {
  1651.       best_index = new_index;
  1652.       best_loc = i + first;
  1653.     }
  1654.   }
  1655.  
  1656.   POV_FREE(area_left);
  1657.   POV_FREE(area_right);
  1658.  
  1659.   /*
  1660.    * Stop splitting if the BUNCHING_FACTOR is reached or
  1661.    * if splitting stops being effective.
  1662.    */
  1663.  
  1664.   if ((size <= BUNCHING_FACTOR) || (best_loc < 0))
  1665.   {
  1666.     cd = create_bbox_node(size);
  1667.       
  1668.     for (i = 0; i < size; i++)
  1669.     {
  1670.       cd->Node[i] = Finite[first+i];
  1671.     }
  1672.  
  1673.     calc_bbox(&(cd->BBox), Finite, first, last);
  1674.  
  1675.     *Root = (BBOX_TREE *)cd;
  1676.  
  1677.     if (*nFinite > maxfinitecount)
  1678.     {
  1679.       /* Prim array overrun, increase array by 50%. */
  1680.  
  1681.       maxfinitecount = 1.5 * maxfinitecount;
  1682.  
  1683.       /* For debugging only. */
  1684.  
  1685.       Debug_Info("Reallocing Finite to %d\n", maxfinitecount);
  1686.  
  1687.       Finite = (BBOX_TREE **)POV_REALLOC(Finite, maxfinitecount * sizeof(BBOX_TREE *), "bounding boxes");
  1688.     }
  1689.  
  1690.     Finite[*nFinite] = cd;
  1691.  
  1692.     (*nFinite)++;
  1693.  
  1694.     return (1);
  1695.   }
  1696.   else
  1697.   {
  1698.     sort_and_split(Root, Finite, nFinite, first, best_loc + 1);
  1699.  
  1700.     sort_and_split(Root, Finite, nFinite, best_loc + 1, last);
  1701.  
  1702.     return (0);
  1703.   }
  1704. }
  1705.  
  1706.